home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 1
/
Gold Medal Software Volume 1 (Gold Medal) (1994).iso
/
graphics
/
povsrc20.arj
/
SOURCE
/
DISCS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-28
|
6KB
|
231 lines
/****************************************************************************
* discs.c
*
* This module implements the disc primitive.
* This file was written by Alexander Enzmann. He wrote the code for
* discs and generously provided us these enhancements.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
METHODS Disc_Methods =
{
All_Disc_Intersections,
Inside_Disc, Disc_Normal,
Copy_Disc, Translate_Disc, Rotate_Disc, Scale_Disc, Transform_Disc,
Invert_Disc, Destroy_Disc
};
extern long Ray_Disc_Tests, Ray_Disc_Tests_Succeeded;
int All_Disc_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
DBL Depth;
VECTOR IPoint;
register int Intersection_Found;
Intersection_Found = FALSE;
if (Intersect_Disc (Ray, (DISC *)Object, &Depth))
{
VScale (IPoint, Ray->Direction, Depth);
VAddEq (IPoint, Ray->Initial);
if (Point_In_Clip (&IPoint, Object->Clip))
{
push_entry(Depth,IPoint,Object,Depth_Stack);
Intersection_Found = TRUE;
}
}
return (Intersection_Found);
}
int Intersect_Disc (Ray, disc, Depth)
RAY *Ray;
DISC *disc;
DBL *Depth;
{
DBL t1, t2, len, tmpf;
VECTOR P, D, tmpv;
Ray_Disc_Tests++;
/* Transform the point into the discs space */
MInvTransPoint(&P, &Ray->Initial, disc->Trans);
MInvTransDirection(&D, &Ray->Direction, disc->Trans);
*Depth = HUGE_VAL;
VLength(len, D);
VInverseScaleEq(D, len);
/* Do the normal ray-plane intersection */
VDot(t1, disc->normal, D);
if (fabs(t1) < 1.0e-10)
return 0;
VDot(t2, disc->normal, P);
t2 = -(t2 + disc->d) / t1;
if (t2 < 0)
return 0;
VScale(tmpv, D, t2);
VAddEq(tmpv, P);
VSub(tmpv, tmpv, disc->center);
VDot(tmpf, tmpv, tmpv);
if (tmpf < disc->iradius2 || tmpf > disc->oradius2)
return 0;
else
*Depth = t2 / len;
if (*Depth < Small_Tolerance || *Depth > Max_Distance)
return FALSE;
Ray_Disc_Tests_Succeeded++;
return TRUE;
}
int Inside_Disc (IPoint, Object)
VECTOR *IPoint;
OBJECT *Object;
{
VECTOR New_Point;
DISC *disc = (DISC *) Object;
DBL tmpf, offset = (disc->Inverted ? -EPSILON : EPSILON);
/* Transform the point into the discs space */
MInvTransPoint(&New_Point, IPoint, disc->Trans);
VDot(tmpf, New_Point, disc->normal);
tmpf += disc->d;
if (tmpf+offset > 0)
return disc->Inverted;
else
return 1 - disc->Inverted;
}
void Disc_Normal (Result, Object, IPoint)
OBJECT *Object;
VECTOR *Result, *IPoint;
{
DISC *disc = (DISC *) Object;
MTransNormal(Result, &disc->normal, disc->Trans);
VNormalize(*Result, *Result);
}
void *Copy_Disc (Object)
OBJECT *Object;
{
DISC *New;
New = Create_Disc();
*New = *((DISC *) Object);
New->Trans = Copy_Transform(((DISC *)Object)->Trans);
return (New);
}
void Translate_Disc (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Translation_Transform(&Trans, Vector);
Transform_Disc(Object, &Trans);
}
void Rotate_Disc (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Rotation_Transform(&Trans, Vector);
Transform_Disc(Object, &Trans);
}
void Scale_Disc (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Scaling_Transform(&Trans, Vector);
Transform_Disc(Object, &Trans);
}
void Invert_Disc (Object)
OBJECT *Object;
{
((DISC *)Object)->Inverted = 1 - ((DISC *)Object)->Inverted;
}
void Transform_Disc (Object, Trans)
OBJECT *Object;
TRANSFORM *Trans;
{
DISC *Disc = (DISC *)Object;
VECTOR lengths;
DBL len;
Compose_Transforms(Disc->Trans, Trans);
/* Recalculate the bounds */
len = sqrt(Disc->oradius2);
Make_Vector(&lengths, len, len, len);
VSub(Disc->Bounds.Lower_Left, Disc->center, lengths);
VScale(Disc->Bounds.Lengths, lengths, 2.0);
recompute_bbox(&Disc->Bounds, Disc->Trans);
}
DISC *Create_Disc ()
{
DISC *New;
if ((New = (DISC *) malloc (sizeof (DISC))) == NULL)
MAError ("disc");
INIT_OBJECT_FIELDS(New, DISC_OBJECT, &Disc_Methods)
Make_Vector (&(New->center), 0.0, 0.0, 0.0);
Make_Vector (&(New->normal), 0.0, 1.0, 0.0);
New->iradius2 = 0.0;
New->oradius2 = 1.0;
New->d = 0.0;
New->Trans = Create_Transform();
New->Inverted = 0;
/* Default bounds */
Make_Vector(&New->Bounds.Lower_Left, -1.0, -EPSILON, -1.0);
Make_Vector(&New->Bounds.Lengths, 2.0, 2*EPSILON, 2.0);
return New;
}
void Destroy_Disc (Object)
OBJECT *Object;
{
Destroy_Transform(((DISC *)Object)->Trans);
free (Object);
}